In computer graphics applications, complex shapes and structures are formed through the sampling, interconnection and rendering of more simple shapes, referred to as primitives. An example of such a primitive is a triangle, or other suitable polygon. These primitives, in turn, are formed by the interconnection of individual pixels. Objects are generated by combining a plurality of pixels together to form a shape (e.g. a cup). Physical attributes, such as color and texture are then applied to the individual pixels based on their location within the primitive and the primitives' orientation with respect to the generated shape. Several objects may be used to create a larger image.
To enhance the presentation of the image, lighting (e.g. luminance value) may be applied to the pixels of the several objects contained within the image. The amount of lighting, or luminance, to be applied to a particular pixel is determined from the point of view of a light source. Conventionally, this is done by determining the angle between rays traced from the light source to the particular point of interest and the angle from the point of interest to the eye position. Typically, the point of interest is at the center of the pixel being illuminated. Such angle and luminance determinations are performed by graphics processor circuitry. The luminance to be applied to a pixel of interest is also affected by the actual visibility of the light source. That visibility can be determined by observing a ray, for example, a line segment linking the light source to the pixel of interest. If an object intersects the ray, then the pixel of interest is in shadow, and the light does not contribute directly to the luminance value of the pixel of interest. Thus, the luminance value associated with a given pixel is determined by objects that are between the light source and the particular pixel of interest.
FIG. 1 is a representative side view of a conventional method for determining the luminance of a pixel of interest within an image. The rendered image includes an object 12 being illuminated by a light source 14. The object 12 can be either static (e.g. a tree) or moving (e.g. a ball) as viewed in eye space from the vantage point of a hypothetical eye 15. A pixel I (to the left of the object 12) will be partially illuminated (e.g. in shadow), while pixel P1 will be fully illuminated.
One distinguishing characteristic between pixels in shadow and pixels in the light is the amount of luminance (i.e. light) that is applied to the pixels. Since the ray d from light source 14 to pixel P1 does not intersect any objects, pixel P1 receives illumination from the light source. The luminance value to be applied to the several pixels that comprise an image is a function of whether they are in shadow and the distance between the pixels and the light source 14 as determined from the point of view of the light source 14 (e.g. in light space). The distance used in performing luminance calculations is the straight-line distance (d) between a particular pixel of interest, for example, P1 and the light source 14.
A drawback associated with conventional luminance calculation methods is that they only allow two choices: the pixel is lit or the pixel is in shadow. This produces aliasing artifacts when the ray from the pixel of interest to the light source passes near an edge of the object, since this produces an abrupt transition between pixels that are illuminated and pixels that are in shadow.
standard luminance calculation methods compare multiple rays to the light source from positions near the pixel of interest. Thus pixels P2 and P3, which are near pixel P1, also contribute to the luminance value at pixel P1, depending on whether any of them are in shadow, that is, depending whether the rays between them and the light source intersect some other object. The comparison results may be used to determine a visibility factor for the pixel of interest. For example, 32 separate rays could be tested and averaged, and if N of them do not intersect another object, the pixel of interest could be marked as being N/32nds visible. The illumination based on the angles and distance could then be multiplied by N/32, resulting in a smooth transition between pixels that are entirely in shadow to pixels that are fully illuminated. The intersection tests could be performed geometrically by computing multiple rays and comparing each ray to each object in the scene, but that is very costly.
A serious drawback associated with conventional luminance calculation methods is that the luminance value is based on a constant straight-line distance (d). Thus, as you move distance d, from pixel to pixel, you traverse a line 16 that at some point is no longer in the same plane as the pixel of interest. Consequently, rays to the light source from pixels P2 and P3 appear to intersect an object in the scene, since they intersect the ground plane containing pixel P1. This is referred to as self-shadowing. Self-shadowing results in unwanted aliasing and/or distortions to be present within the resulting rendered image, as the luminance values for the pixels that lie below the plane of the pixel of interest will be incorrectly included as shadowed pixels in calculating the luminance value of the pixel of interest; thereby, causing the pixel of interest to have less luminance than it actually should. As illustrated in FIG. 1, self-shadowing causes pixels at positions that should be illuminated (e.g. P2, P3) to be placed in shadow (e.g. or be given little luminance) as the constant linear distance of line 16 places those corresponding pixels at locations below the plane of the object in the image that contains P1, the pixel being illuminated. Stated differently, the pixels (P2, P3) will no longer be in the same plane as the pixel of interest (e.g. P1); thereby adversely affecting the luminance value of P1.
An alternative method to ray casting techniques, the Shadow Buffer algorithm, renders a scene as if it were viewed from the position of the light source and computes the distance from the light source to the nearest object along each ray, using a standard depth buffer algorithm that is known in the art. The resulting set of depth values is called a shadow buffer or shadow map. To perform the intersection test, the shadow buffer algorithm computes the distance from the light source at the point of interest and compares it to the depth values stored in the shadow buffer that are near the ray that passes from the point of interest to the light source. If the distance from the light source to the point of interest is greater than the depth recorded in the shadow buffer, then the nearby ray is shadowed, since it intersects an object that is closer to the light than the point of interest.
A drawback associated with the Shadow Buffer algorithm is that a single depth value at the point of interest is compared to multiple nearby depth values in the shadow buffer. This results in the same inaccurate luminance value determinations as described above, since the object that the pixel is part of typically is not perpendicular to the light source. Therefore, each of the nearby vectors should compute a different distance to the light source. Failing to do this again causes the artifact called “self shadowing”, in which a point of interest is shadowed by the object that it is part of. Conventional solutions to this problem reduce the distance d to the light source by the expected amount of self-shadowing. This reduces but may not entirely eliminate self-shadowing. It also produces artifacts that remove shadows when objects are close to each other.